//
//  NFCUint.swift
//  AESOLAR_IOS
//
//  Created by Mr.wang on 2018/12/24.
//  Copyright © 2018 Mr.wang. All rights reserved.
//

import UIKit
import CoreNFC

class NFCUint: NSObject {

    private var readingAvailable: Bool {
        if #available(iOS 11.0, *) {
//            if (TARGET_IPHONE_SIMULATOR == 1 && TARGET_OS_IPHONE == 1) {
//                return false
//            }
            return NFCNDEFReaderSession.readingAvailable
        } else {
            return false
        }
    }
    
    var cancelClosure: () -> () = { }
    var successClosure: (String) -> () = {_ in }
    var nfcErrorClosure: (String) -> () = {_ in }
    var timeOutClosuer: () -> () = { }
    var session: NFCReaderSession? = nil
    
    var timer: Timer?
    var time: Int = 0
    var autoTimeOut = false
    
    private var succeed = false
    private var isPreparing = false
    
    func initializeNFCSession() {
        guard !isPreparing else { return }
        if #available(iOS 13.0, *) {
            let session = NFCTagReaderSession.init(pollingOption: .iso15693, delegate: self, queue: DispatchQueue.main)
            session?.alertMessage = "请将手机贴近组件上黏贴的标签".localized
            session?.begin()
            self.session = session
            isPreparing = true
            APPHud.shared.showLoading(text: "请稍后".localized)
        }
    }
    
    func beginScan() {
        guard readingAvailable else {
            nfcErrorClosure("当前设备不支持NFC功能".localized)
            return
        }
        
        guard #available(iOS 13.0, *) else {
            nfcErrorClosure("扫描TAG功能只支持iOS 13系统".localized)
            return
        }
        
        succeed = false
        initializeNFCSession()
    }
    
    func showError(_ message: String) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
            self?.nfcErrorClosure(message)
        }
    }
    
    func bytesToStr(bytes: [UInt8]) -> String {
        return bytes.map{ $0.description }
            .map { string -> String in
                let strInt = Int(string) ?? 0
                let low = strInt % 16
                let hight = strInt / 16
                return hexIntToStr(HexInt: hight) + hexIntToStr(HexInt: low)
            }.joined()
    }
    
    func hexIntToStr(HexInt: Int) -> String {
        if HexInt > 9 {
            switch HexInt{
            case 10: return "A"
            case 11: return "B"
            case 12: return "C"
            case 13: return "D"
            case 14: return "E"
            case 15: return "F"
            default: return "0"
            }
        } else {
            return String(HexInt)
        }
    }
    
    @objc func timeOut() {
        if self.time == 15 {
            self.timeOutClosuer()
            self.session?.invalidate()
            self.timer?.invalidate()
            return
        }
        self.time += 1
    }
    
    deinit {
        print("NFCUint    ---    deinit")
    }
    
}

@available(iOS 13.0, *)
extension NFCUint: NFCTagReaderSessionDelegate {
    
    func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
        isPreparing = false
        APPHud.shared.dismiss()
        
        if autoTimeOut {
            timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timeOut), userInfo: nil, repeats: true)
            RunLoop.main.add(timer!, forMode: .common)
        }
    }
    
    func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
        isPreparing = false
        APPHud.shared.dismiss()
        typealias NFCCode = NFCReaderError.Code
        if error.code == NFCCode.readerSessionInvalidationErrorUserCanceled.rawValue && !succeed {
            cancelClosure()
            timer?.invalidate()
        } else if error.code == NFCCode.readerSessionInvalidationErrorSessionTimeout.rawValue {
            self.timeOutClosuer()
            self.session?.invalidate()
        } else if error.code == NFCCode.readerSessionInvalidationErrorSystemIsBusy.rawValue {
            showError("系统正忙，开启NFC失败，请稍后再试".localized)
        } else if !succeed {
            showError(error.localizedDescription)
        }
    }
    
    func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
        guard let tag = tags.first,
            case let .iso15693(isoTag) = tag else { return }
        succeed = true
        let UDID = self.bytesToStr(bytes: [UInt8](isoTag.identifier).reversed())
        session.invalidate()
        timer?.invalidate()
        successClosure(UDID)
    }
    
}
